/** FC合集,基础按键根据游戏修改,
  基础按键依次为:a,b,start,select,连发a,连发b(因为start,select,连发a和连发b都可省略)
  模拟器预设1:d,x,r,f,c,s -B攻A跳类
  预设2:x,d,r,f,s,c - A攻B跳类
  预设3:d,d,r,f,a,s - ab起跳类
  By setycyas @2025-05-18
*/

/* 全局设定
*/ {
#Warn
#MaxThreadsPerHotkey 1
SetWorkingDir(A_ScriptDir)
#Include "..\Class\FaceDetector.2.ahk"
#Include "..\Class\CommonMacro.2.ahk"
#Include "..\Class\CommonUI.2.ahk"
#Include "..\Class\MyFuns.2.ahk"
#Include "..\Class\MyEmu.2.ahk"
#Include "..\Class\OrderMap.2.ahk"
;SendMode("Event")
SendMode("Input")
}

/* 制作Fc的宏类
*/ class FCMacro extends CommonMacro {

  pressDuration := 30

  /* 函数
  */

  /* 新增的宏函数
  */
  ;单发
  _单宏模拟(i, key){
    local vk
    this._down(i)
    vk := GetKeyVK(MyFuns.getHotkey(key))
	  ;sleep(this.autoFireDelay)
    loop {
	    sleep(this.autoFireDelay)
    } until (not MyFuns.getVkState(vk))
    this._up(i)
  }
  _单发A(key){
    this._单宏模拟(1, key)
  }
  _单发B(key){
    this._单宏模拟(2, key)
  }
  _单发start(key){
    this._单宏模拟(3, key)
  }
  ;ab
  _AB(key){
    this._down(1)
    this._down(2)
    sleep(60)
    this._up(1)
    this._up(2)
  }
  ;蓄力
  _蓄力A(key){
    this._down(1)
  }
  _蓄力B(key){
    this._down(2)
  }
  ;轻微位移用
  _右微移(key){
    MyFuns.press("right", 50)
    sleep(50)
  }
  _左微移(key){
    MyFuns.press("left", 50)
    sleep(50)
  }
  ;其他
  _后跳(key){
    local back := this._face.back()
    ;MyFuns.pressKeys([this._keys[1], back], [this.testParams[1], 50])
    this._down(1)
    MyFuns.keyDown(back)
    sleep(50)
    this._up(1)
    MyFuns.keyUp(back)
  }
  _上B(key){
    MyFuns.keyDown("up")
    this._press(2)
    MyFuns.keyUp("up")	  
  }
  ;成龙之龙用
  _小AB(key){
  	this._down(1)
  	sleep(30)
  	this._down(2)
  	sleep(30)
  	this._up(1)
  	this._up(2)
  }
  ;SD快打旋风专用
  ;连发ab
  _按住B后A连发(key){
  	MyFuns.clearDirections()
    this._down(2)
    sleep(30)
    this._连发A(key)
    sleep(30)
    this._up(2)
  }
  ;B+前,必杀技
  _B前(key){
  	local face := this._face.face()
    this._down(2)
    sleep(30)
    MyFuns.press(face, 50)
    this._up(2)	
  }
  ;Guy的后跳必杀,按住触发放手解除
  _Guy后跳必杀(key){
  	;local face := this._face.face()
    local back := this._face.back()	
    this._press(1)
    sleep(30)
    MyFuns.press(back, 50)
    sleep(30)
    MyFuns.keyDown("up")
    sleep(50)
    this._连发B(key)
    MyFuns.keyUp("up")
  }
  ;cody升龙拳
  _Cody升龙拳(key){
    this._B前(key)
    sleep(this.testParams[1])
    MyFuns.keyDown("up")
    sleep(30)
    this._连发B(key)
    MyFuns.keyUp("up")	
  }
  
  /* 重载宏接口
  */
  _setMacro(){
    static obm := ObjBindMethod ;函数名简写,制作对象绑定函数
    local m := OrderMap() ;this.macroMap的简写
    ;制作宏相关Map
    this.macroMap := m
    ;通用
    m["连发A"] := obm(this, "_连发A")
    m["连发B"] := obm(this, "_连发B")
    m["单发A"] := obm(this, "_单发A")
    m["单发B"] := obm(this, "_单发B")
    m["单发start"] := obm(this, "_单发start")
    m["蓄力A"] := obm(this, "_蓄力A")
    m["蓄力B"] := obm(this, "_蓄力B")
    m["AB"] := obm(this, "_AB")
    m["后跳"] := obm(this, "_后跳")
    m["左微移"] := obm(this, "_左微移")
    m["右微移"] := obm(this, "_右微移")
    m["空函数"] := obm(this, "_空函数")
    ;上+攻击键出招类通用
    m["上B"] := obm(this, "_上B")
    ;成龙之龙用
    m["小AB"] := obm(this, "_小AB")
    ;SD快打旋风用
    m["按住B后A连发"] := obm(this, "_按住B后A连发")
    m["B前"] := obm(this, "_B前")
    m["Guy后跳必杀"] := obm(this, "_Guy后跳必杀")
    m["Cody升龙拳"] := obm(this, "_Cody升龙拳")
    ;制作指定宏顺序的数组
    this.macroArr := m.getKeys()
  }
}

/* 制作FC专用UI
*/
class FCUI extends CommonUI {

  HOTKEY_NUM := 8
  EXE_ARRAY := ["fceux.exe", MyEmu.FBNEO64, MyEmu.MAME, MyEmu.XZONE]
  
  /* 构造函数
  */
  __New(macro){
    super.__New("FC合集", macro)
    local preset := OrderMap() ;部分预设表
    this._preset := OrderMap()
    this._macro.UI := this ;绑定UI
    ;设置preset和提升蓄力宏的优先级
    ;部分预设
    ;preset["B攻连A跳单"] := ["连发B", "单发A", "单发B", "连发A"]
    ;preset["A攻连B跳单"] := ["连发A", "单发B", "单发A", "连发B"]
    preset["6空函数"] := ["空函数", "空函数", "空函数", "空函数", "单发start", "空函数", "空函数"] ;除a和最后的start都是空的
    preset["7空函数"] := ["空函数", "空函数", "空函数", "空函数", "空函数", "单发start", "空函数", "空函数"] ;全空除最后start 
    ;实际预设
    ;;this._preset["B攻连A跳单"] := MyFuns.arrCombine(preset["B攻连A跳单"], preset["后4按键标准"])
    ;this._preset["A攻连B跳单"] := MyFuns.arrCombine(preset["A攻连B跳单"], preset["后4按键标准"])
    ;this._preset["上B"] := this._preset["B攻连A跳单"].Clone()
    this._preset["只有start"] := preset["7空函数"].Clone()
    this._preset["上B"] := MyFuns.arrCombine(["上B"], preset["6空函数"]) ;基础按键:d,x,r,f,c,s-B连攻A单跳
    this._preset["上B"][2] := "左微移"
    this._preset["上B"][3] := "右微移"
    this._preset["三目童子"] := preset["7空函数"].Clone() ;基础按键:d,a,r,f,c,q
    this._preset["三目童子"][4] := "蓄力B"
    this._preset["三目童子"][7] := "连发B" ;释放蓄力需要用手动脚本连发
    this._preset["成龙之龙"] :=  MyFuns.arrCombine(["小AB"], preset["6空函数"]) ;基础按键:d,w,r,f,c,q
    this._preset["成龙之龙"][4] := "蓄力B"
    this._preset["成龙之龙"][7] := "连发B"
    this._preset["帝国战机"] := preset["7空函数"].Clone() ;基础按键:d,w,e,f,c,s
    this._preset["帝国战机"][6] := "AB"
    this._preset["SD快打旋风"] := MyFuns.arrCombine(
    	["B前", "Cody升龙拳", "Guy后跳必杀", "空函数", "空函数", "按住B后A连发"],
      ["空函数", "空函数"]) ;基础按键:d,x,r,f,c,s-B连攻A单跳
  }

  /* 重写接口
  */
  ;自定义gui组件标签页,增加一个挡板召唤键
  _customGui(){
    super._customGui()
  }

  /* 重写setup,更改可选的exe,读入预设
  */
  setup(){
    super.setup()
    this._myGui.opt("+AlwaysOnTop")
    this._myGui.show("x1100 y230")
    this.readPresetMenu("上B")
  }
  
  /* 自定义函数
  */
  
}

/* 运行当前脚本
*/ 
if (A_ScriptName == "FC合集轻度版.2.ahk") {
  face := FaceDetector() ;方向检测对象
  macro := FCMacro(face, ["d","x","r","f", "c", "s"]) ;宏对象,有界面时第二个参数可以随便写但长度不要小于2
  ;新建界面对象并显示
  ui := FCUI(macro)
  ui.setup()
  ;更新组件内容
  ui._exeComboBox.Choose("fceux.exe")
  ;ui._exeComboBox.Choose(MyEmu.FBNEO64)
  ui._gameKeyEdit.Text := "d,x,r,f,c,s" ;B攻A跳
  ;ui._gameKeyEdit.Text := "d,w,r,f,c,q" ;成龙之龙
  ;ui._gameKeyEdit.Text := "d,a,r,f,c,q" ;三目童子
  ;ui._gameKeyEdit.Text := "x,d,r,f,s,c" ;A攻B跳
  ;ui._gameKeyEdit.Text := "d,d,r,f,a,s" ;AB起跳类
  ui._hotkeyEdit.Text := "~a,~w,~e,~x,~c,~space,~s,~d"
  ui._fpsEdit.Text := 15
  ui._testEdit.Text := "50,100,30,30"
  ui.readPresetMenu("上B")
}
